mod auth;

use axum::Router;
use axum::routing::post;
use axum_common::extractor::{Path, UserStore, ValidForm, ValidJson};
use axum_common::server::app;
use axum_common::{ApiResult, R, router, func_path};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::HashMap;
use tracing::log;
use axum_common::middleware::Principal;
use validator::{Validate, ValidationError};
use axum_common::scheduled::{delete_scheduled, save_scheduled, Scheduled};
use axum_common::scheduler::{register, BoxFuture};

fn main() {
    register(func_path!(foo).to_string(), foo);
    let nest = router![
        ("/user1", create_user);
        ("/user2", create_user2);
        ("/white_list1", white_list1);
        ("/white_list2/{id}", white_list2);
        ("/white_list3/{*path}", white_list3);
    ];
    let router = Router::new()
        .route("/login", post(auth::login))
        .route("/add/scheduler", post(add_scheduler))
        .route("/del/scheduler", post(del_scheduler))
        .nest("/users", nest);

    app::run(router);
}

async fn add_scheduler() -> R<()> {
    let task = func_path!(foo).to_string();
    let scheduled = Scheduled {
        business_id: 1,
        business_type: None,
        cron: Some("*/1 * * * * *".to_string()),
        task,
        start_time: None,
    };
    save_scheduled(scheduled).await.into()
}

async fn del_scheduler() -> R<()> {
    delete_scheduled(1, None).await.into()
}

pub fn foo(id: i64) -> BoxFuture {
    Box::pin(async move {
        log::info!("foo:{id}")
    })
}

async fn create_user(
    UserStore(principal): UserStore<Principal>,
    ValidJson(create_user): ValidJson<CreateUser>,
) -> R<User> {
    println!("{principal:?}");
    R::success(User {
        id: 1,
        username: create_user.username,
    })
}

async fn create_user2(ValidForm(create_user): ValidForm<CreateUser>) -> R<User> {
    R::success(User {
        id: 1,
        username: create_user.username,
    })
}

async fn white_list1() -> R<&'static str> {
    R::success("White list1")
}
async fn white_list2(Path(id): Path<u8>) -> R<String> {
    R::success(format!("White list2: {id}"))
}

async fn white_list3(Path(path): Path<String>) -> R<String> {
    R::success(format!("White list3: {path}"))
}

#[derive(Deserialize, Validate)]
struct CreateUser {
    #[validate(
        length(min = 1, max = 5, message = "长度必须在1到5之间"),
        custom(function = "validate_unique_username")
    )]
    username: String,

    #[validate(range(min = 1, message = "最小为1"))]
    age: u8,
}

fn validate_unique_username(username: &str) -> ApiResult<(), ValidationError> {
    if username == "sjt" {
        return Err(ValidationError {
            code: Cow::from("invalid"),
            message: Some(Cow::from("使用禁用词")),
            params: HashMap::new(),
        });
    }

    Ok(())
}

#[derive(Serialize)]
struct User {
    id: u64,
    username: String,
}
